﻿using System;
using Deferred.Library.Configuration;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Deferred.Library
{
    /// <summary>
    /// 
    /// </summary>
    public class FpsCounter : GraphicalComponent
    {
        private DeferredBase deferredBase;
        private bool visible = false;
        private float updateInterval = 1.0f;
        private float timeSinceLastUpdate = 0.0f;
        private float framecount = 0;

        private SpriteFont font;
        private SpriteBatch batcher;

        private float fps = 0;

        /// <summary>
        /// 
        /// </summary>
        protected override bool LoadContentUponCreation { get { return false; } }
        /// <summary>
        /// 
        /// </summary>
        public float FPS { get { return fps; } }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="deferredBase"></param>
        public FpsCounter(DeferredBase deferredBase)
            : base(deferredBase.DeviceService)
        {
            this.deferredBase = deferredBase;

            if (GraphicsDevice != null) LoadContent();
        }

        /// <summary>
        /// 
        /// </summary>
        public void Initialize()
        {
            IOptions options = (IOptions)deferredBase.Services.GetService(typeof(IOptions));
            if (options != null) options.AddOption("Diagnostic.DisplayFPS", false, delegate(bool value) { visible = value; });
        }

        /// <summary>
        /// 
        /// </summary>
        protected override void LoadContent()
        {
            batcher = new SpriteBatch(GraphicsDevice);
            font = deferredBase.Content.InternalContent.Load<SpriteFont>("FpsFont");
        }

        /// <summary>
        /// 
        /// </summary>
        protected override void DestroyContent()
        {
            batcher.Dispose();
        }

        /// <summary>
        /// Update the fps.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public void Update(GameTime gameTime)
        {
            float elapsed = (float)gameTime.ElapsedRealTime.TotalSeconds;
            framecount++;
            timeSinceLastUpdate += elapsed;

            if (timeSinceLastUpdate > updateInterval)
            {
                fps = framecount / timeSinceLastUpdate; //mean fps over updateIntrval
                framecount = 0;
                timeSinceLastUpdate -= updateInterval;

                if (Updated != null)
                    Updated(this, new EventArgs());
            }
        }

        /// <summary>
        /// FpsCounter Updated Event.
        /// </summary>
        public event EventHandler<EventArgs> Updated;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="gameTime"></param>
        public void Draw(GameTime gameTime)
        {
            if (visible)
            {
                batcher.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.SaveState);
                batcher.DrawString(font, fps.ToString() + " frames/second", new Vector2(0, 0), Color.White);
                batcher.End();
            }
        }
    }
}
